﻿// ===============================================================================
// XCI.WinForm.Platform 西安交通信息WinForm开发框架 2019 版权所有
// ===============================================================================

using System;
using System.ComponentModel;
using System.Windows.Forms;
using DevExpress.Data.Filtering;
using DevExpress.XtraEditors;
using DevExpress.XtraEditors.Popup;
using DevExpress.XtraTreeList;
using DevExpress.XtraTreeList.Nodes;
using XCI.Core;
using XCI.Extensions;
using XCI.Helper;

namespace XCI.Windows
{
    /// <summary>
    /// 省市区县树形下拉控件
    /// </summary>
    [System.ComponentModel.DesignerCategory("Code")]
    public class AreaTreeListLookUpEdit : TreeListLookUpEdit
    {
        private bool shown;
        private object _dataObject;

        /// <summary>
        /// 是否默认合上所有节点
        /// </summary>
        [Category("XCI"), DefaultValue(true), Description("是否默认合上所有节点")]
        public virtual bool IsDefaultCollapseAll { get; set; } = true;

        /// <summary>
        /// 省份标识字段
        /// </summary>
        [Category("对象"), Description("省份标识字段"), DefaultValue(null)]
        public string ProvinceIdField { get; set; }

        /// <summary>
        /// 省份名称字段
        /// </summary>
        [Category("对象"), Description("省份名称字段"), DefaultValue(null)]
        public string ProvinceNameField { get; set; }

        /// <summary>
        /// 城市标识字段
        /// </summary>
        [Category("对象"), Description("城市标识字段"), DefaultValue(null)]
        public string CityIdField { get; set; }

        /// <summary>
        /// 城市名称字段
        /// </summary>
        [Category("对象"), Description("城市名称字段"), DefaultValue(null)]
        public string CityNameField { get; set; }

        /// <summary>
        /// 区县标识字段
        /// </summary>
        [Category("对象"), Description("区县标识字段"), DefaultValue(null)]
        public string CountyIdField { get; set; }

        /// <summary>
        /// 区县名称字段
        /// </summary>
        [Category("对象"), Description("区县名称字段"), DefaultValue(null)]
        public string CountyNameField { get; set; }

        /// <summary>
        /// 街道标识字段
        /// </summary>
        [Category("对象"), Description("街道标识字段"), DefaultValue(null)]
        public string TownIdField { get; set; }

        /// <summary>
        /// 街道名称字段
        /// </summary>
        [Category("对象"), Description("街道名称字段"), DefaultValue(null)]
        public string TownNameField { get; set; }

        /// <summary>
        /// 取值和设值数据对象
        /// </summary>
        [Browsable(false), DefaultValue(null), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public object DataObject
        {
            get
            {
                if (_dataObject == null) return null;

                var val = GetAreaValue();
                SetDataObjectValue(_dataObject, val.Province, ProvinceIdField, ProvinceNameField);
                SetDataObjectValue(_dataObject, val.City, CityIdField, CityNameField);
                SetDataObjectValue(_dataObject, val.County, CountyIdField, CountyNameField);
                SetDataObjectValue(_dataObject, val.Town, TownIdField, TownNameField);
                return _dataObject;
            }
            set
            {
                _dataObject = value;
                if (_dataObject == null) return;
                var df = AreaDataManager.GetDataObjectField(_dataObject);
                ProvinceIdField = df.ProvinceIdField;
                ProvinceNameField = df.ProvinceNameField;
                CityIdField = df.CityIdField;
                CityNameField = df.CityNameField;
                CountyIdField = df.CountyIdField;
                CountyNameField = df.CountyNameField;
                TownIdField = df.TownIdField;
                TownNameField = df.TownNameField;

                var v = new AreaValue
                {
                    Province = new AreaModel
                    {
                        Id = ObjectHelper.GetObjectProperty(_dataObject, ProvinceIdField).ToStringOrEmpty(),
                        Name = ObjectHelper.GetObjectProperty(_dataObject, ProvinceNameField).ToStringOrEmpty()
                    },
                    City = new AreaModel
                    {
                        Id = ObjectHelper.GetObjectProperty(_dataObject, CityIdField).ToStringOrEmpty(),
                        Name = ObjectHelper.GetObjectProperty(_dataObject, CityNameField).ToStringOrEmpty()
                    },
                    County = new AreaModel
                    {
                        Id = ObjectHelper.GetObjectProperty(_dataObject, CountyIdField).ToStringOrEmpty(),
                        Name = ObjectHelper.GetObjectProperty(_dataObject, CountyNameField).ToStringOrEmpty()
                    },
                    Town = new AreaModel
                    {
                        Id = ObjectHelper.GetObjectProperty(_dataObject, TownIdField).ToStringOrEmpty(),
                        Name = ObjectHelper.GetObjectProperty(_dataObject, TownNameField).ToStringOrEmpty()
                    }
                };
                SetAreaValue(v);
            }
        }

        private void SetDataObjectValue(object dataObject, AreaModel model, string idField, string nameField)
        {
            if (dataObject == null || model == null) return;

            ObjectHelper.SetObjectProperty(dataObject, idField, model.Id);
            ObjectHelper.SetObjectProperty(dataObject, nameField, model.Name);
        }

        /// <summary>
        /// 重写窗体处理的消息
        /// </summary>
        /// <param name="m">消息</param>
        protected override void WndProc(ref Message m)
        {
            //private const int WM_CREATE = 0x0001;
            switch (m.Msg)
            {
                case 0x0001://当控件刚创建的时候，就捕获该消息，然后将控件的文本清空。
                    Text = string.Empty;
                    break;
                default://其他消息由父类处理。
                    base.WndProc(ref m);
                    break;
            }
        }

        protected override void OnCreateControl()
        {
            base.OnCreateControl();
            if (DesignMode) return;

            this.Properties.ValueMember = nameof(AreaModel.Id);
            this.Properties.DisplayMember = nameof(AreaModel.Name);
            this.Properties.PopupWidthMode = PopupWidthMode.UseEditorWidth;
            var treelist = this.Properties.TreeList;
            if (treelist == null) return;
            treelist.Columns.AddRange(new[] {
                new DevExpress.XtraTreeList.Columns.TreeListColumn
                {
                    Caption = "名称",
                    FieldName = nameof(AreaModel.Name),
                    Name = "treeColName",
                    Visible = true,
                    VisibleIndex = 0
                }});
            treelist.KeyFieldName = "Id";
            treelist.ParentFieldName = "ParentId";
            treelist.TreeViewFieldName = nameof(AreaModel.Name);
            treelist.OptionsSelection.EnableAppearanceFocusedCell = false;
            treelist.OptionsView.FocusRectStyle = DevExpress.XtraTreeList.DrawFocusRectStyle.None;
            treelist.OptionsView.ShowColumns = false;
            treelist.OptionsView.ShowHorzLines = false;
            treelist.OptionsView.ShowIndicator = false;
            treelist.OptionsView.ShowVertLines = false;
            treelist.OptionsView.ShowFilterPanelMode = DevExpress.XtraTreeList.ShowFilterPanelMode.Never;
            treelist.OptionsView.ShowAutoFilterRow = true;
            treelist.OptionsFilter.FilterMode = FilterMode.EntireBranch;
            treelist.OptionsFilter.ExpandNodesOnFiltering = true;
            treelist.OptionsBehavior.AutoPopulateColumns = false;

            var imageCollection1 = new DevExpress.Utils.ImageCollection();
            imageCollection1.InsertGalleryImage("images/maps/geopoint_16x16.png", "images/maps/geopoint_16x16.png", DevExpress.Images.ImageResourceCache.Default.GetImage("images/maps/geopoint_16x16.png"), 0);
            imageCollection1.Images.SetKeyName(0, "images/maps/geopoint_16x16.png");
            treelist.SelectImageList = imageCollection1;
            treelist.SubstituteFilter += Treelist_SubstituteFilter;
            Properties.DataSource = AreaDataManager.GetTreeCollection();
        }

        protected override void OnPopupShown()
        {
            var focusedNode = Properties.TreeList.FocusedNode;
            if (IsDefaultCollapseAll && !shown)
            {
                shown = true;
                Properties.TreeList.CollapseToLevel(0);
            }
            base.OnPopupShown();
            if (focusedNode != null)
            {
                Properties.TreeList.FocusedNode = focusedNode;
            }
        }

        /// <summary>
        /// 获取省市区县值
        /// </summary>
        /// <returns></returns>
        public AreaValue GetAreaValue()
        {
            var model = new AreaValue();
            var editValue = EditValue;
            if (editValue == null || string.IsNullOrEmpty(editValue.ToString())) return model;
            var fnode = Properties.TreeList.FindNodeByKeyID(editValue);
            if (fnode == null) return model;

            SetNodeToModel(model, fnode);
            RecursionParentNode(fnode, n =>
            {
                SetNodeToModel(model, n);
            });
            return model;
        }

        /// <summary>
        /// 设置省市区县值
        /// </summary>
        /// <param name="v"></param>
        public void SetAreaValue(AreaValue v)
        {
            object editValue = null;
            if (v.Town != null && !string.IsNullOrEmpty(v.Town.Id))
            {
                editValue = v.Town.Id;
            }
            else if (v.County != null && !string.IsNullOrEmpty(v.County.Id))
            {
                editValue = v.County.Id;
            }
            else if (v.City != null && !string.IsNullOrEmpty(v.City.Id))
            {
                editValue = v.City.Id;
            }
            else if(v.Province != null && !string.IsNullOrEmpty(v.Province.Id))
            {
                editValue = v.Province.Id;
            }
            this.EditValue = editValue;
        }

        private void SetNodeToModel(AreaValue model, TreeListNode node)
        {
            if (!(Properties.TreeList.GetDataRecordByNode(node) is AreaModel rowObject)) return;
            if (rowObject.Type == 1)
            {
                model.Province = rowObject;
            }
            else if (rowObject.Type == 2)
            {
                model.City = rowObject;
            }
            else if (rowObject.Type == 3)
            {
                model.County = rowObject;
            }
            else if (rowObject.Type == 4)
            {
                model.Town = rowObject;
            }
        }

        /// <summary>
        /// 递归父节点
        /// </summary>
        /// <param name="node"></param>
        /// <param name="action"></param>
        public void RecursionParentNode(TreeListNode node, Action<TreeListNode> action)
        {
            if (node.ParentNode == null) return;
            var parentNode = node.ParentNode;
            action(parentNode);
            RecursionParentNode(parentNode, action);
        }

        private void Treelist_SubstituteFilter(object sender, DevExpress.Data.SubstituteFilterEventArgs e)
        {
            FunctionOperator f1 = (FunctionOperator)e.Filter;
            var key = ((OperandValue)f1.Operands[1]).Value.ToStringOrEmpty();
            FunctionOperator f2 = new FunctionOperator(FunctionOperatorType.Contains, new OperandProperty(nameof(AreaModel.Spell)), key);
            e.Filter = CriteriaOperator.Or(f1, f2);
        }

        protected override PopupBaseForm CreatePopupForm()
        {
            return base.CreatePopupForm();
        }
    }
}